﻿#region Header

/*
    This file is part of ndoctor-statistics.

    ndoctor-statistics is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    ndoctor-statistics is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with ndoctor-statistics.  If not, see <http://www.gnu.org/licenses/>.
*/

#endregion Header

namespace Probel.NDoctor.Statistics.Components
{
    using System;
    using System.Linq;

    using Probel.NDoctor.Statistics.Domain;

    /// <summary>
    /// Provides queries that returns only one result
    /// </summary>
    internal class ScalarQuery : Query, IScalarQuery
    {
        #region Constructors

        public ScalarQuery(IRepository repository)
            : base(repository)
        {
        }

        #endregion Constructors

        #region Properties

        private DateTime Today
        {
            get
            {
                return DateTime.Today;
            }
        }

        #endregion Properties

        #region Methods

        /// <summary>
        /// Counts the active users. A user is active when he/she used the application at lease one time this last week.
        /// </summary>
        /// <param name="lastActivity">If the user logged statistics withing the specified number of days, it is selected.</param>
        /// <returns>
        /// The count of active users
        /// </returns>
        public double GetActiveApplicationCount(int lastActivity = 14)
        {
            return (from user in this.Repository.Applications
                    where user.LastUpdate > this.Today.AddDays(0 - lastActivity)
                    select user).Count();
        }

        /// <summary>
        /// Gets the user by app key.
        /// </summary>
        /// <param name="appKey">The app key.</param>
        /// <param name="version">The version.</param>
        /// <returns>
        /// The application or null if doesn't exist
        /// </returns>
        public Application GetApplicationByAppKey(Guid appKey)
        {
            var now = DateTime.Now.ToUniversalTime();
            return (from u in this.Repository.Applications
                    where u.ApplicationKey == appKey
                    select u).SingleOrDefault();
        }

        /// <summary>
        /// Counts the users registered in the database.
        /// </summary>
        /// <returns></returns>
        public double GetApplicationCount()
        {
            return this.Repository.Applications.Count();
        }

        /// <summary>
        /// Gets the average execution time of a method of a component.
        /// </summary>
        /// <returns>
        /// The average execution time of the methods
        /// </returns>
        public double GetAvgExecutionTime()
        {
            var result = (from a in this.Repository.Statistics
                          select a.ExecutionTime);

            return (result.Count() != 0) ? result.Average() : 0;
        }

        /// <summary>
        /// Gets the count of durations.
        /// </summary>
        /// <returns></returns>
        public double GetDurationCount()
        {
            return this.Repository.Durations.Count();
        }

        /// <summary>
        /// Gets the first inscription.
        /// </summary>
        /// <returns>
        /// The date of the first inscription
        /// </returns>
        public DateTime GetFirstInstallation()
        {
            var query = this.Repository.Applications;
            return (query.Count() > 0)
                ? query.Min(e => e.InstallationDate).ToLocalTime()
                : DateTime.MinValue;
        }

        /// <summary>
        /// Gets the last inscription.
        /// </summary>
        /// <returns>
        /// The date of the last inscription
        /// </returns>
        public DateTime GetLastInstallation()
        {
            var query = this.Repository.Applications;
            return (query.Count() > 0)
                ? query.Max(e => e.InstallationDate).ToLocalTime()
                : DateTime.MinValue;
        }

        /// <summary>
        /// Get the date and the time of the last update.
        /// </summary>
        /// <returns>
        /// A <see cref="DateTime"/> representing the last update of the statistics
        /// </returns>
        public DateTime GetLastUpdate()
        {
            var query = this.Repository.Applications;
            return (query.Count() > 0)
                ? query.Max(e => e.LastUpdate).ToLocalTime()
                : DateTime.MinValue;
        }

        /// <summary>
        /// Gets the number of statistics entries contained in the database.
        /// </summary>
        /// <returns>
        /// The number of statistics entries in the database
        /// </returns>
        public double GetStatisticsCount()
        {
            return this.Repository.Statistics.Count();
        }

        #endregion Methods
    }
}